﻿using System;
using System.IO;
using System.Text.RegularExpressions;

namespace SoftwareMonkeys.LogClimber.Business
{
	/// <summary>
	/// Description of LogRepairer.
	/// </summary>
	public class LogRepairer
	{
		
        /// <summary>
        /// Repairs any potential and expected issues with a log so it can be loaded.
        /// </summary>
        /// <param name="logFilePath">The path to the log.</param>
        /// <returns>The path to the repaired log.</returns>
        public string RepairLogFile(LogGrower grower, string logFilePath)
        {
            if (grower.LogsDirectoryPath == String.Empty || grower.LogsDirectoryPath == null)
                throw new InvalidOperationException("The LogsDirectoryPath property hasn't been set.");

            string logPath = logFilePath;
            string fixedLogPath = Path.GetDirectoryName(logFilePath) +
                Path.DirectorySeparatorChar + "RepairedLog.xml";

            string logContents;

            using (StreamReader reader = new StreamReader(File.OpenRead(logPath)))
            {
                logContents = reader.ReadToEnd();
                reader.Close();
            }

            logContents = RepairLog(logContents);


            using (StreamWriter writer = File.CreateText(fixedLogPath))
            {
                writer.Write(logContents);
                writer.Close();
            }

            return fixedLogPath;
        }
        
        public string RepairLog(string logContents)
        {
        	logContents = RemoveExtraXmlTags(logContents);

        	logContents = RemoveExtraCloseOpenLogTags(logContents);

        	logContents = RemoveExtraOpenLogTags(logContents);

			
        	// TODO: Check if needed. Should be obsolete.

            // Add the start <Log> tag if necessary

           // string startTag = "<Log>";

           // if (logContents.IndexOf(startTag) == -1)

            //    logContents = startTag + "\r\n" + logContents;


            logContents = AddXmlTag(logContents);

            logContents = AddCloseLogTag(logContents);
            
            return logContents;
        }
        
        public string RemoveExtraXmlDeclarationTags(string logContents)
        {
        
            // Remove any duplicate <?xml .... ?> tags

            logContents = new Regex("\n<(/?.)xml(.+)(/?.)>", RegexOptions.IgnoreCase | RegexOptions.Multiline)

                .Replace(logContents, "\n");
            
            return logContents;
        }
        
        public string RemoveExtraCloseOpenLogTags(string logContents)
        {
           // Remove any duplicate </Log>...<Log> tags

            logContents = new Regex("</Log>(.|\r\n)*?<Log>", RegexOptions.IgnoreCase | RegexOptions.Multiline)

                .Replace(logContents, "");
            
            return logContents;
        }
        
        public string RemoveExtraOpenLogTags(string logContents)
        {
        

           // Remove any duplicate <Log> tags

           Regex brokenStartLogRegEx = new Regex("</Entry>(.|\n)*?<Log>", RegexOptions.IgnoreCase | RegexOptions.Multiline);
           
            logContents = brokenStartLogRegEx

                .Replace(logContents, "</Entry>");
            
            return logContents;
        }
        
        public string AddXmlTag(string logContents)
        {
        
            // Add the XML declaration if necessary

            // This must be done before after the start tag prepend won't work

            string xmlDeclaration = "<?xml version=\'1.0\'?>";

            if (logContents.IndexOf(xmlDeclaration) == -1)

                logContents = xmlDeclaration + "\r\n" + logContents;

            return logContents;
        }
        
        public string AddCloseLogTag(string logContents)
        {
        
            // Add the ending </Log> tag if necessary

            if (logContents.IndexOf("</Log>") == -1)

                logContents = logContents + "</Log>\n";
            
            return logContents;
        }
	}
}
